<?php
include_once('vendor/autoload.php');

class AliSms {

// 阿里云短信API地址
    const API_URL = 'https://dysmsapi.aliyuncs.com/';
    
    // 接口版本
    const API_VERSION = '2017-05-25';
    
    // 签名方法
    const SIGNATURE_METHOD = 'HMAC-SHA1';
    
    // 签名版本
    const SIGNATURE_VERSION = '1.0';
    
    private $accessKeyId;
    private $accessKeySecret;
    
    /**
     * 构造函数
     * @param string $accessKeyId 阿里云AccessKeyId
     * @param string $accessKeySecret 阿里云AccessKeySecret
     */
    public function __construct($accessKeyId, $accessKeySecret) {
        $this->accessKeyId = $accessKeyId;
        $this->accessKeySecret = $accessKeySecret;
    }
    
    /**
     * 发送短信验证码
     * @param string $phoneNumbers 手机号，多个用逗号分隔
     * @param string $signName 签名名称
     * @param string $templateCode 模板CODE
     * @param array $templateParam 模板参数
     * @return array 接口返回结果
     */
    public function sendSmsCode($phoneNumbers, $signName, $templateCode, $templateParam = []) {
        // 组装请求参数
        $params = [
            'Action' => 'SendSms',
            'Version' => self::API_VERSION,
            'AccessKeyId' => $this->accessKeyId,
            'SignatureMethod' => self::SIGNATURE_METHOD,
            'SignatureVersion' => self::SIGNATURE_VERSION,
            'SignatureNonce' => uniqid(),
            'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
            'PhoneNumbers' => $phoneNumbers,
            'SignName' => $signName,
            'TemplateCode' => $templateCode
        ];
        
        // 添加模板参数
        if (!empty($templateParam)) {
            $params['TemplateParam'] = json_encode($templateParam, JSON_UNESCAPED_UNICODE);
        }
        
        // 生成签名
        $params['Signature'] = $this->generateSignature($params);
        
        // 发送请求
        $response = $this->sendRequest($params);
        if(strpos($response,'<Code>0</Code>') || strpos($response,'<Code>OK</Code>')){
            
            return true;
        }

        return false;
    }
    
    /**
     * 生成签名
     * @param array $params 请求参数
     * @return string 签名结果
     */
    private function generateSignature($params) {
        // 对参数进行排序
        ksort($params);
        
        // 拼接参数
        $canonicalizedQueryString = '';
        foreach ($params as $key => $value) {
            $canonicalizedQueryString .= '&' . $this->encode($key) . '=' . $this->encode($value);
        }
        
        // 去除第一个&
        $canonicalizedQueryString = ltrim($canonicalizedQueryString, '&');
        
        // 构造待签名的字符串
        $stringToSign = "GET&%2F&" . $this->encode($canonicalizedQueryString);
        
        // 计算签名
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $this->accessKeySecret . '&', true));
        
        return $signature;
    }
    
    /**
     * 发送HTTP请求
     * @param array $params 请求参数
     * @return string 响应内容
     */
    private function sendRequest($params) {
        // 构建请求URL
        $url = self::API_URL . '?' . http_build_query($params);
        
        // 初始化cURL
        $ch = curl_init();
        
        // 设置cURL选项
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 生产环境建议开启SSL验证
        // 如果需要禁用SSL验证（不推荐生产环境），可以开启下面这行
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        
        // 执行请求
        $response = curl_exec($ch);
        
        // 处理错误
        if (curl_errno($ch)) {
            throw new Exception('cURL错误: ' . curl_error($ch));
        }
        
        // 关闭cURL
        curl_close($ch);
        
        return $response;
    }
    
    /**
     * URL编码
     * @param string $str 要编码的字符串
     * @return string 编码后的字符串
     */
    private function encode($str) {
        $result = urlencode($str);
        $result = preg_replace('/\+/', '%20', $result);
        $result = preg_replace('/\*/', '%2A', $result);
        $result = preg_replace('/%7E/', '~', $result);
        return $result;
    }
}